PAM execution on logon
Why
During development of a project I wanted to be able to only allow a single logon through sFTP.
Every subsequent logons should fail.
Although there are different ways to achieve the same functionality, I wanted PAM to initiate the sFTP credential deletion.
Basic Idea
sFTP Logon with user + priv key
v
[PAM] User & key is valid
v
[PAM] Call script => remove public key
v
[PAM] Logon successful
What is PAM
GNU/Linux uses the Pluggable Authentication Modules (PAM) to handle authentication of different services.
All PAM applicable modules are stored under the path /etc/pam.d/
.
If we take a look at the /etc/pam.d/sshd
module we see the following calls to object libraries:
- Comments are removed
@include common-auth
account required pam_nologin.so
@include common-account
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
session required pam_loginuid.so
session optional pam_keyinit.so force revoke
@include common-session
session optional pam_motd.so motd=/run/motd.dynamic
session optional pam_motd.so noupdate
session optional pam_mail.so standard noenv # [1]
session required pam_limits.so
session required pam_env.so # [1]
session required pam_env.so user_readenv=1 envfile=/etc/default/locale
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
@include common-password
- Every "
session
" runs a different action on the new session logon. session
entries that have therequired
flag will hard fail and terminate the authentication.
Adding your own PAM module
- Needs sshd installed
Edit /etc/pam.d/sshd
and append the following line right before @include common-passwod
:
...
session required pam_exec.so seteuid /path/to/your/script.sh # << Add this line
@include common-password
seteuid
will instructpam_exec.so
to run the script with the permissions of the logon user and populates PAM user variables.- Switch out
require
withoptional
you're testing.
Accessing variables
Now on every ssh logon PAM will execute the script.
Inside the script we can access individual variables to determine an action.
pam_exec.so
populates the following variables:
PAM_RHOST
=> IP of the remote hostPAM_RUSER
=> Logon usernamePAM_SERVICE
=> Service that PAM used (sshd/sudo/etc.)PAM_TTY
=> path of the TTYPAM_TYPE
=> contains eitheropen_session
orclose_session
depending of the action.
This should now allow you to build a bash script to execute certain actions on specific service logons.
Example script
#!/bin/bash
if [ "$PAM_USER" == "user1" ] && [ "$PAM_TYPE" == "open_session" ]; then
# overwrite a key file
echo > /path/to/key
fi
Hardening SFTP
As a small tidbit here's a configuration how you can harden the sFTP logon:
ForceCommand internal-sftp
forces ssh to load sftp-u 0666
sets the default umask-p realpath,open,write,close,lstat
blacklists the ftp commands
This allows the user1 to connect to sFTP and create files but not to download or read directory contents.
/etc/ssh/sshd_config.d/sftp.conf
Match User user1
ForceCommand internal-sftp -u 0666 -p realpath,open,write,close,lstat
AuthorizedKeysFile /path/to/keyfile
PubKeyAuthentication yes
PasswordAuthentication no
ChrootDirectory /path/to/chroot/dir
PermitTunnel no
AllowAgentForwarding no
AllowTcpForwarding no
X11Forwarding no
Chroot permission issues
The ChrootDirectory
needs to be owned by root and not writable by anybody else:
$ ls /path/to/chroot/dir
drwxr-xr-x 3 root root 4.0K Dec 20 00:00 .
SSHD will create it's own user directory in there so there is no need to create additional directories.